//
//  EOCPerson.m
//  Test
//
//  Created by 杨德龙 on 2017/3/7.
//  Copyright © 2017年 HipalSports. All rights reserved.
//

#import "EOCPerson.h"
#import "EOCEmployer.h"  //EOCPerson 类的实现则需引入EOCEmployer 类的头文件 因为若要使用后者则必须知道其所有接口细节.

/*
 将引入头文件的时机尽量延后,只在确有需要时才引入,这样就可以减少类的使用者所需引入的头文件数量.
 假如 把EOCEmployer.h 引入到 EOCPerson.h 中那么 只要引入 EOCPerson.h .就会一并引入EOCEmployer.h
 中所有的内容.  次过程持续下去 则要引入许多根本用不到的内容 ,这回增加编译时间
 */


@implementation EOCPerson


- (instancetype)initWithFirstName:(NSString *)firstName
                         lastName:(NSString *)lastName
{
    self=[super init];
    if (self) {
        _firstName=[firstName copy];
        _lastName=[lastName copy];
    }
    return self;
}


- (void)setFirstName:(NSString *)firstName
{
    if (_firstName!=firstName) {
        _firstName=firstName;
    }
}

#pragma mark ----  两种 setter 和 getter 方法对比



- (void)setFullName:(NSString *)fullName
{
    NSArray *components=[fullName componentsSeparatedByString:@" "];
    self.firstName=[components objectAtIndex:0];
    self.lastName=[components objectAtIndex:1];
    
}

- (NSString *)fullName
{
    return [NSString stringWithFormat:@"%@ %@",self.firstName,self.lastName];
}


/*
    1.0 由于不经过OC的方法派发,所以直接访问实例变量的速度比较快. 在这种情况下,编译器会直接访问保存对象实例内存
    2.0 在ARC 下直接访问一个声明为copy的属性, 那么并不会拷贝改属性,只会保留新值并释放旧值
    3.0 直接访问不会触发KVO . 而设置方法是可以触发KVO的
    折中方法:  设置用 "设置方法"来做  ,读取直接访问
 */
- (void)setInstanceFullName:(NSString *)instanceFullName
{
    NSArray *components=[instanceFullName componentsSeparatedByString:@" "];
    _firstName=[components objectAtIndex:0];
    _lastName=[components objectAtIndex:1];
}

- (NSString *)instanceFullName
{
    return [NSString stringWithFormat:@"%@ %@",_firstName,_lastName];

}


#pragma mark ----  等同性测试  

- (BOOL)isEqual:(id)object
{
    if (self==object) {
        return YES;
    }
    
    if ([self class] != [object class]) {
        return NO;
    }
    
    EOCPerson *otherPerson=(EOCPerson *)object;
    if (![_firstName isEqualToString:otherPerson.firstName]) {
        return NO;
    }
    
    if (![_lastName isEqualToString:otherPerson.lastName]) {
        return NO;
    }
    
    return YES;
}


/**
 这是 一种 兼顾 高效率 和 哈希码 不过去 频繁重复的 问题

 @return return value description
 */
- (NSUInteger)hash
{
    NSUInteger firstNameHash=[_firstName hash];
    NSUInteger lastNameHash=[_lastName hash];
    
    return firstNameHash^lastNameHash;
}

/*
   这种性能较低  因为创建了字符串
 - (NSUInteger)hash
 {
 NSString *stringToHash=[NSString stringWithFormat:@"%@%@",_firstName,_lastName];
 return [stringToHash hash];
 }
 */


#pragma mark ---- Description   和  DebugDescription


/**
 一般 我们返回<>  中包含地址 然后各个属性名称和值的 一个字符串

 @return
 */
- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">",[self class],self,_firstName,_lastName];
}


/**
 下面这种 是debugDescription 的显示  我们在编译期间 使用PO 命令显示 注意这种字典的 是推荐的方法

 @return return value description
 */
- (NSString *)debugDescription
{
    return [NSString stringWithFormat:@"<%@: %p, %@>",[self class],self,@{@"firstName":_firstName,@"lastName":_lastName}];

}








@end
